home *** CD-ROM | disk | FTP | other *** search
- Path: news.primenet.com!jstern
- From: jstern@Primenet.Com (Josh Stern)
- Newsgroups: comp.lang.c++
- Subject: Re: Templates, Pointers to Members and Static Initialization
- Date: 3 Apr 1996 03:41:00 -0700
- Organization: Primenet Services for the Internet
- Sender: root@primenet.com
- Message-ID: <4jtkjs$8se@nnrp1.news.primenet.com>
- References: <4jp0bd$2h7@blue.usps.gov>
- X-Posted-By: jstern@usr6.primenet.com
-
- Bill Seymour <wseymour@email.usps.gov> wrote:
- >I need to create a static const associative array of descriptors for
- >members of arbitrary structures. It's known that all members will have
- >type char[] and contain null-terminated strings. My first idea for one
- >element of such an array is:
- >
- > struct MemberDescriptor
- > {
- > const char* name;
- > ptrdiff_t offset;
- > size_t size;
- > char* GetString(void* str) const { return (char*)str + offset; }
- > };
- >
- >but offset can't be statically initialized without an offsetof operator.
- >(Magic numbers are out of the question, of course; and a macro that
- >expands to the difference between two pointers isn't a constant.)
-
- I'm not sure of exactly what you are trying to do, but
- I think that your best bet would go like this:
-
- 1) if you know exactly how many of these 'elements' you have then
- declare this as a const int (in whatever scope/namespace is
- appropriate); otherwise, pick some dummy value for the record
- and let that act like '\0' for strings - i.e. put the dummy
- value last in your initializer list so when you get to it
- you know that is the end.
-
- 2) build a dynamic associative map using the array from
- one - this can still be a static global variable so long
- as it takes such an array as an initializer. Here is
- a rough sketch assuming the 'unknown' case from 1) - I'll
- use STL's map container:
-
- #include <map.h>
- #include <string.h>
-
- struct MemberDescriptor
- {
- const char* name;
- const char* SomeOtherThing; // just for concreteness
- // put whatever info here
- };
-
- // Really, it would be better to use a String class instead of const char*
-
- MemberDescriptor Data[] = { {"Name1", "description1"}, \
- {"Name2", "description2"}, \
- {"Name3", "description3"}, \
- {"END",""} }; // "END" is special value
-
- struct STRC { // Comparator required for map
- bool operator() (const char* x, const char* y) const {
- return (strcmp(x,y) < 0);
- }
- };
-
- class ArrMap {
- public:
- typedef map<const char* const,const char*, STRC > mp; // all work done here
- typedef mp::iterator iterator;
- protected:
- mp m;
- public:
- ArrMap(MemberDescriptor* yourdata) : m() { // constructor fills map
- MemberDescriptor* tptr = yourdata;
- const char* str;
- while (strcmp((str = tptr->name),"END")) {
- m[str] = tptr++->SomeOtherThing;
- }
- }
- const char*& operator[](const char*& x) { return m[x]; }
-
- // Duplicate rest of interface to map, including operator[], or see below
- };
-
- /* Rather than having the map as a member of ArrMap it would
- be more convenient to have ArrMap as a derived class, but initializing
- it as a static object would then involve special purpose iterators
- that I didn't want to bother to write in.
- */
-
-
- ArrMap yourmap(Data);
-
- // Testing...(not very creatively)
- void main(void)
- {
- cout << '\n' << yourmap["Name1"] << '\n'
- << yourmap["Name2"] << '\n'
- << yourmap["Name3"] << '\n';
-
- }
-
- /****************************************************/
-
- - Josh
-
-
- --
- -------------------------------------------------------------------------------
- jstern
- jstern@primenet.com
- -------------------------------------------------------------------------------
-